package org.xtext.runtime.plan;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.xtext.runtime.formula.IFormula;
import org.xtext.runtime.interpreter.Agent;
import org.xtext.runtime.term.Variable;
import org.xtext.runtime.util.Bindings;

public class ForEachStep implements IPlanStep {
	private IFormula guard;
	private IPlanStep body;
	
	public ForEachStep(IFormula guard, IPlanStep plan) {
		this.guard = guard;
		this.body = plan;
	}
	
	@Override
	public ForEachStep apply(Bindings set) {
		guard.apply(set);
		body.apply(set);
		return this;
	}

	public String toString() {
		return toString("");
	}
	
	public String toString(String tabs) {
		return tabs + "foreach (" + guard + ") ...";
	}

	public String toFullString(String tabs) {
		return tabs + "foreach (" + guard + ")" + body.toFullString(tabs + IPlanStep.TAB);
	}

	public IFormula guard() {
		return guard;
	}
	
	public IPlanStep plan() {
		return body;
	}
	
	@Override
	public void handle(Agent agent, PlanStack planStack) {
		List<Bindings> result = agent.queryAll(guard);
		if (result != null) {
			if (result.isEmpty()) {
				planStack.addPlanStep(body);
			} else {
				for(Bindings bindings : result) {
					planStack.addPlanStep(body.copy(new HashMap<String, Variable>()).apply(bindings));
				}
			}
			planStack.getNextActivity().handle(agent, planStack);
		}
	}

	@Override
	public Set<Variable> variables() {
		Set<Variable> variables = new HashSet<Variable>();
		variables.addAll(guard.variables());
		variables.addAll(body.variables());
		return variables;
	}

	@Override
	public IPlanStep copy(Map<String, Variable> vars) {
		return new ForEachStep(guard.copy(vars), body.copy(vars));
	}

	@Override
	public void reset() {
	}
}
